package com.shuiyun.log.aspect;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shuiyun.log.anno.LogAnno;
import com.shuiyun.log.dao.LogDAO;
import com.shuiyun.log.enums.LogType;
import com.shuiyun.log.po.LogPO;
import com.shuiyun.log.vo.LogDesc;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * @program: LogDemo
 * @description: 日志切面
 * @author: gujun
 * @create: 2019-10-10 13:43
 **/
@Aspect
@Component
public abstract class LogAspect {

    @Autowired
    private LogDAO logDAO;
    @Autowired
    private AfterCommitExecutor afterCommitExecutorImpl;
    private ThreadLocal<String> thread = new ThreadLocal<>();
    private String message = null;
    private String userName = null;

    public abstract String getUserName();

    public void setUserName(){
        this.userName = this.getUserName();
    }


    /**
     * 定义切面为标注有PrivateAnno注解的方法
     * @param logAnno
     */
    @Pointcut("@annotation(logAnno)")
    public void doAuthToken(LogAnno logAnno){
    }


    /**
     * 环绕通知实现权限验证
     * @param point
     * @param anno
     * @return
     * @throws Throwable
     */
    @Around("doAuthToken(anno)")
    public Object doBefore(ProceedingJoinPoint point, LogAnno anno) throws Throwable {
        Object[] args = point.getArgs();
        LogType logType = anno.logType();
        boolean active = false;

        if (null == thread.get()){
            active = true;
            thread.set(UUID.randomUUID().toString());
        }
        //设置用户名
        this.setUserName();

        Object proceed = point.proceed();
        boolean isActive = active;
        afterCommitExecutorImpl.execute(() -> {
            saveLog(logType,proceed,isActive,thread.get());
            if (null != thread.get()){
                thread.set(null);
            }
        });
        return proceed;
    }



    private void saveLog(LogType logType, Object proceed,boolean isActive,String optId) {
        LogPO log = new LogPO();
        //如果是新增
        if (LogType.INSERT.equals(logType)){
            JSONObject data = JSON.parseObject(JSON.toJSONString(proceed));
            log.set_id(RandomUtil.randomString(20));
            log.setDataId(data.getString("id"));
            log.setOptId(optId);
            log.setModule(1001);//用户模块
            System.out.println("当前登录："+userName);
            log.setType(logType.getValue());
            if (isActive){
                log.setDesc("张三新增了一个用户:"+log.getDataId());
                message = log.getDesc();
            }else{
                log.setDesc("因为"+message+"所以张三新增了一个用户");
            }
            log.setOptName("张三");
            log.setIsActive(isActive);
            log.setOptTime(new Date());
            log.setAfterMsg(data.toJSONString());
            logDAO.save(log);
        }
        //如果是更新
        if (LogType.UPDATE.equals(logType)){
            JSONObject data = JSON.parseObject(JSON.toJSONString(proceed));
            String dataId = data.getString("id");
            LogPO preLog = logDAO.findFirstByModuleAndDataIdOrderByOptTimeDesc(1001, dataId);
            String afterMsg = preLog.getAfterMsg();
            log.set_id(RandomUtil.randomString(20));
            log.setDataId(dataId);
            log.setOptId(optId);
            log.setIsActive(isActive);
            System.out.println("当前登录："+userName);
            log.setModule(1001);//用户更新模块
            log.setType(logType.getValue());
            if (isActive){
                log.setDesc("张三修改了一个用户"+log.getDataId());
                message = log.getDesc();
            }else{
                log.setDesc("因为"+message+"所以张三修改了一个用户");
            }
            log.setOptName("张三");
            log.setOptTime(new Date());
            log.setBeforeMsg(afterMsg);
            log.setAfterMsg(data.toJSONString());
            logDAO.save(log);
        }
    }
}
